package com.rocching.easychat.db;

import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.rocching.easychat.entity.DocumentEntity;
import com.rocching.easychat.util.JsonUtil;
import com.rocching.easychat.util.StringUtil;

import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;

public abstract class DocumentService<T> {
    private static final String TAG = DocumentService.class.getName();
    protected EasyChatSQLiteOpenHelper helper;
    protected String type;

    protected DocumentService(String type) {
        helper = EasyChatSQLiteOpenHelper.getInstance();
        this.type = type;
    }

    public void insert(String objectId, T model) {
        try {
            ContentValues contentValues = new ContentValues();
            contentValues.put(DocumentEntity.FIELD_NAME_OBJECT_ID, objectId);
            contentValues.put(DocumentEntity.FIELD_NAME_TYPE, type);
            contentValues.put(DocumentEntity.FIELD_NAME_CONTENT, JsonUtil.toJson(model));
            SQLiteDatabase db = helper.getWritableDatabase();

            db.insert(DocumentEntity.TABLE_NAME, null, contentValues);
        } catch (Exception e) {
            Log.e(TAG, e.getMessage(), e);
        }
    }

    public int update(String objectId, T model) {
        try {
            ContentValues contentValues = new ContentValues();
            contentValues.put(DocumentEntity.FIELD_NAME_CONTENT, JsonUtil.toJson(model));

            SQLiteDatabase db = helper.getWritableDatabase();
            String[] args = {objectId};
            return db.update(DocumentEntity.TABLE_NAME, contentValues, DocumentEntity.FIELD_NAME_OBJECT_ID + "=?", args);
        } catch (Exception e) {
            Log.e(TAG, e.getMessage(), e);
            return 0;
        }
    }

    public int update(String objectId, Class<T> tClass, Consumer<T> consumer) {
        T model = getById(objectId, tClass);
        if (consumer != null) {
            consumer.accept(model);
        }
        return update(objectId, model);
    }

    public List<T> getAll(Class<T> tClass) {
        try {
            SQLiteDatabase db = helper.getReadableDatabase();
            Cursor cursor = db.rawQuery(getBaseSql(), new String[]{type});

            List<T> list = new LinkedList<>();
            while (cursor.moveToNext()) {
                String content = "";
                int index = cursor.getColumnIndex(DocumentEntity.FIELD_NAME_CONTENT);
                if (index > -1) {
                    content = cursor.getString(index);
                }

                if (StringUtil.isNotEmpty(content)) {
                    T model = JsonUtil.parseObject(content, tClass);
                    if (!Objects.isNull(model)) {
                        list.add(model);
                    }
                }
            }
            cursor.close();
            return list;
        } catch (Exception e) {
            Log.e(TAG, e.getMessage(), e);
            return null;
        }
    }

    public T get(Class<T> tClass) {
        List<T> list = getAll(tClass);
        if (StringUtil.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }

    public T getById(String objectId, Class<T> tClass) {
        if (StringUtil.isEmpty(objectId)) {
            return null;
        }
        try {
            String sql = getBaseSql() + " AND " + DocumentEntity.FIELD_NAME_OBJECT_ID + "=?";

            String[] args = new String[]{type, objectId};
            SQLiteDatabase db = helper.getReadableDatabase();
            Cursor cursor = db.rawQuery(sql, args);

            T model = null;
            while (cursor.moveToNext()) {
                String content = "";
                int index = cursor.getColumnIndex(DocumentEntity.FIELD_NAME_CONTENT);
                if (index > -1) {
                    content = cursor.getString(index);
                }

                if (StringUtil.isNotEmpty(content)) {
                    model = JsonUtil.parseObject(content, tClass);
                    if (!Objects.isNull(model)) {
                        break;
                    }
                }
            }
            cursor.close();
            return model;
        } catch (Exception e) {
            Log.e(TAG, e.getMessage(), e);
            return null;
        }
    }

    public int deleteAll() {
        try {
            SQLiteDatabase db = helper.getWritableDatabase();
            return db.delete(DocumentEntity.TABLE_NAME, String.format("%s=?", DocumentEntity.FIELD_NAME_TYPE), new String[]{type});
        } catch (Exception e) {
            Log.e(TAG, e.getMessage(), e);
            return 0;
        }
    }

    public int deleteById(String objectId) {
        if (StringUtil.isEmpty(objectId)) {
            return -1;
        }
        try {
            SQLiteDatabase db = helper.getWritableDatabase();
            return db.delete(DocumentEntity.TABLE_NAME, String.format("%s=? AND %s=?", DocumentEntity.FIELD_NAME_TYPE, DocumentEntity.FIELD_NAME_OBJECT_ID), new String[]{type, objectId});
        } catch (Exception e) {
            Log.e(TAG, e.getMessage(), e);
            return 0;
        }
    }

    private String getBaseSql() {
        return String.format(" select * from %s WHERE %s=? ", DocumentEntity.TABLE_NAME, DocumentEntity.FIELD_NAME_TYPE);
    }
}
